/**
 Signal and Slot for Java
 Copyright (C) 2003 Thia Yeo Ching (tycordinal@yahoo.co.uk)
 http://sourceforge.net/projects/javasignalslot/

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package org.arclib.examples.signal; 

import org.arclib.signal.*; 

/**
 * Author: Thia Yeo Ching, tycordinal@yahoo.co.uk
 * Date: Mar 26, 2003
 * Time: 2:57:48 AM
 */
public class TestSignalSlotMap
{
  public static void main(String args[])
  {
    Producer p = new Producer();
    IntObject io = new IntObject(1);

    StringObject so = new StringObject();
    so.o = "hello";


    NeedInt ni = new NeedInt();
    NeedString ns = new NeedString();
    NeedAll na = new NeedAll();

    //SignalSlotMap.connect(p, Producer.INT_SIGNAL, ni, NeedInt.INT_SLOT, IntObject.class);
    //SignalSlotMap.connect(p, Producer.STR_SIGNAL, ni, NeedInt.INT_SLOT, IntObject.class); // make error

    SignalSlotMap.connect(p, Producer.INT_SIGNAL, SlotProviderMethodPair.create(ni, "setIntObject", IntObject.class) );
    SignalSlotMap.connect(p, Producer.STR_SIGNAL, SlotProviderMethodPair.create(ns, "setStringObject",new Class[]{StringObject.class}));

    SignalSlotMap.connect(p, Producer.INT_SIGNAL, SlotProviderMethodPair.create(na, "setIntObject", new Class[] {IntObject.class}) );
    SignalSlotMap.connect(p, Producer.STR_SIGNAL, SlotProviderMethodPair.create(na, "setStringObject",new Class[]{StringObject.class}));

    SignalSlotMap.connect(p, Producer.WAKEUP_SIGNAL, SlotProviderMethodPair.create(na, "wakeUp") );

    SignalSlotMap.disconnect((ISlotProvider) p);  // shall have no effect
    //SignalSlotMap.disconnect((ISignalProvider)p);  // no more signal ! must indicate that it is now ISignalProvider
    //SignalSlotMap.disconnect(na);  // not going to receive anything
    //SignalSlotMap.disconnect(p, Producer.INT_SIGNAL, SlotProviderMethodPair.create(ni, "setIntObject", new Class[] {IntObject.class}) ); // exact match

    System.out.println("1st emit: to all");
    p.doEmit(Producer.INT_SIGNAL, io);
    p.doEmit(Producer.STR_SIGNAL, new Object[] {so});
    SignalSlotMap.emit(p, Producer.WAKEUP_SIGNAL);

    ExtendedIntObject xio = new ExtendedIntObject(1, 2);
    xio.o = 2;
    xio.x = 3;
    System.out.println("emit xio");
    p.doEmit(Producer.INT_SIGNAL, new Object[] {xio});

    //SignalSlotMap.disconnect(p, SlotProviderMethodPair.create(ni, "setIntObject", new Class[] {IntObject.class}) );
    SignalSlotMap.disconnect(p, ni);

    System.out.println("2nd emit: to ns and na");
    p.doEmit(Producer.INT_SIGNAL, new Object[] {io});
    p.doEmit(Producer.STR_SIGNAL, new Object[] {so});
    SignalSlotMap.emit(p, Producer.WAKEUP_SIGNAL);

    SignalSlotMap.disconnect(p, ns);

    System.out.println("3rd emit: only to na");
    p.doEmit(Producer.INT_SIGNAL, new Object[] {io});
    p.doEmit(Producer.STR_SIGNAL, new Object[] {so});
    SignalSlotMap.emit(p, Producer.WAKEUP_SIGNAL);

    SignalSlotMap.disconnect(p, SlotProviderMethodPair.create(na, "setStringObject",new Class[]{StringObject.class}));

    System.out.println("4th emit: to na, no setStringObject");
    p.doEmit(Producer.INT_SIGNAL, new Object[] {io});
    p.doEmit(Producer.STR_SIGNAL, new Object[] {so});
    SignalSlotMap.emit(p, Producer.WAKEUP_SIGNAL);

    SignalSlotMap.disconnect(p, na);

    System.out.println("5th emit: to no one");
    p.doEmit(Producer.INT_SIGNAL, new Object[] {io});
    p.doEmit(Producer.STR_SIGNAL, new Object[] {so});
    SignalSlotMap.emit(p, Producer.WAKEUP_SIGNAL);

    System.out.println("Emit primitives:1");
    SignalSlotMap.connect(p, Producer.SIG_PRIMITIVE_int, SlotProviderMethodPair.create(WantPrimitive.class, "give", new Class[] {int.class}) );
    SignalSlotMap.connect(p, Producer.SIG_DO_NOTHING, SlotProviderMethodPair.create(WantPrimitive.class, "doNothing"));
    int i = 3;
    p.doEmit(Producer.SIG_PRIMITIVE_int, new Object[] {PrimitiveWrapper.wrap(i)});
    p.doEmit(Producer.SIG_DO_NOTHING);

    SignalSlotMap.disconnect(p, SlotProviderMethodPair.create(WantPrimitive.class, "give", new Class[] {int.class}) );
    System.out.println("Emit primitives:2");
    p.doEmit(Producer.SIG_PRIMITIVE_int, new Object[] {PrimitiveWrapper.wrap(i)});
    p.doEmit(Producer.SIG_DO_NOTHING);

    SignalSlotMap.disconnect(p, Producer.SIG_DO_NOTHING, SlotProviderMethodPair.create(WantPrimitive.class, "doNothing"));
    System.out.println("Emit primitives:3");
    p.doEmit(Producer.SIG_PRIMITIVE_int, new Object[] {PrimitiveWrapper.wrap(i)});
    p.doEmit(Producer.SIG_DO_NOTHING);

  }
}

class ExtendedIntObject extends IntObject
{
  public ExtendedIntObject(int i, int j)
	{
		super(i);
		x = j;
		// TODO Auto-generated constructor stub
	}

int x;
}

class StringObject
{
  String o;

  public String toString()
  {
    return this.getClass().getName() + ":" + o;
  }
}

class NamedObject
{
  String name;

  public NamedObject(String name)
  {
    this.name = name;
  }

  public String toString()
  {
    return name;
  }
}


class IntObject
{
  int o;

  public IntObject(int i)
{
	// TODO Auto-generated constructor stub
	 o = i; 
}

public String toString()
  {
    return this.getClass().getName() + ":" + Integer.toString(o);
  }
}

class WantPrimitive implements ISlotProvider
{
  public static void give (int v)
  {
    System.out.println("WantPrimitive.give:int:" + v);
  }

  public static void give (double v)
  {
    System.out.println("WantPrimitive.give:double:" + v);
  }

  public static void give (float v)
  {
    System.out.println("WantPrimitive.give:float:" + v);
  }

  public static void give (byte v)
  {
    System.out.println("WantPrimitive.give:byte:" + v);
  }
  public static void give (boolean v)
  {
    System.out.println("WantPrimitive.give:boolean:" + v);
  }
  public static void give (short v)
  {
    System.out.println("WantPrimitive.give:short:" + v);
  }
  public static void give (long v)
  {
    System.out.println("WantPrimitive.give:long:" + v);
  }
  public static void give (char v)
  {
    System.out.println("WantPrimitive.give:char:" + v);
  }

  public static void doNothing()
  {
    System.out.println("WantPrimitive.doNothing:called");
  }

}

class Producer implements ISignalProvider, ISlotProvider
{
  public static final String SIG_PRIMITIVE_int = "SIG_PRIMITIVE_int";
  public static final String SIG_DO_NOTHING = "SIG_DO_NOTHING";
  public static final String INT_SIGNAL = "INT_SIGNAL";
  public static final String STR_SIGNAL = "STR_SIGNAL";
  public static final String WAKEUP_SIGNAL = "WAKEUP_SIGNAL";  // no signal object

  public void doEmit(String signalName, Object data)
  {
    SignalSlotMap.emit(this, signalName, data);
  }

  public void doEmit(String signalName, Object data[])
  {
    SignalSlotMap.emit(this, signalName, data);
  }

  public void doEmit(String signalName)
  {
    SignalSlotMap.emit(this, signalName);
  }
}

/***
1st emit: to all
NeedInt:got Int:1
NeedAll:got Int:1
NeedString:got String:hello
NeedAll:got String:hello
NeedAll:Yes i am awake!
emit xio
NeedInt:got Int:2
NeedAll:got Int:2
2nd emit: to ns and na
NeedAll:got Int:1
NeedString:got String:hello
NeedAll:got String:hello
NeedAll:Yes i am awake!
3rd emit: only to na
NeedAll:got Int:1
NeedAll:got String:hello
NeedAll:Yes i am awake!
4th emit: to na, no setStringObject
NeedAll:got Int:1
NeedAll:Yes i am awake!
5th emit: to no one
Emit primitives:1
WantPrimitive.give:int:3
WantPrimitive.doNothing:called
Emit primitives:2
WantPrimitive.doNothing:called
Emit primitives:3
Process terminated with exit code 0
 ***/